<template>
    <view class="custom-image" :style="imgStyle" @click="previewImageFn">
        <!-- 占位符 -->
        <view v-if="showPlaceholder" class="placeholder">
            <u-icon v-if="!loading" name="photo" size="24" color="#c8c9cc" />
            <u-loading-icon v-else mode="spinner" size="24" />
        </view>

        <!-- 图片 -->
        <image
            v-show="!showPlaceholder"
            :src="processedSrc"
            @error="handleImageError"
            @load="handleImageLoad"
            :mode="mode"
            :lazy-load="lazyLoad"
            :fade-show="fadeShow"
            :class="{ 'fade-in': imageLoaded, 'no-fade': !fadeShow }"
        />
    </view>
</template>

<script setup lang="ts">
import { ref, computed, watch, type CSSProperties } from 'vue'
import { getImageUrl } from '@/utils'

interface ImageProps {
    src: string
    mode?: string
    width?: string
    height?: string
    isIcon?: boolean
    imgs?: string[]
    lazyLoad?: boolean
    fadeShow?: boolean
    preview?: boolean
    borderRadius?: string
    backgroundColor?: string
}

const props = withDefaults(defineProps<ImageProps>(), {
    src: '',
    mode: 'aspectFill',
    width: '80rpx',
    height: '80rpx',
    isIcon: false,
    imgs: () => [],
    lazyLoad: true,
    fadeShow: true,
    preview: true,
    borderRadius: '4rpx',
    backgroundColor: '#f5f5f5'
})

const emit = defineEmits<{
    load: [event: any]
    error: [event: any]
    click: []
    progress: [progress: number]
}>()

// 处理图片 URL
const processedSrc = computed(() => {
    if (!props.src) return ''

    // 如果是完整 URL，直接返回
    if (props.src.startsWith('http') || props.src.startsWith('data:') || props.src.startsWith('/static/')) {
        return props.src
    }

    // 相对路径，拼接基础 URL
    return getImageUrl(props.src)
})

// 状态管理
const loading = ref(false)
const hasError = ref(false)
const imageLoaded = ref(false)

// 计算属性
const imgStyle = computed(() => {
    const obj: CSSProperties = {
        width: props.width,
        height: props.height,
        borderRadius: props.borderRadius,
        overflow: 'hidden',
        position: 'relative'
    }

    if (!props.isIcon) {
        return Object.assign(obj, {
            backgroundColor: props.backgroundColor
        })
    }

    return obj
})

const showPlaceholder = computed(() => {
    return loading.value || hasError.value || !imageLoaded.value
})

// 事件处理
const handleImageError = (event: any) => {
    console.log('❌ 图片加载失败:', processedSrc.value, event)
    loading.value = false
    hasError.value = true
    imageLoaded.value = false
    emit('error', event)
}

const handleImageLoad = (event: any) => {
    console.log('🖼️ 图片加载成功:', processedSrc.value)
    loading.value = false
    hasError.value = false
    imageLoaded.value = true
    emit('load', event)
}

const previewImageFn = () => {
    emit('click')
    if (!props.preview || hasError.value) return

    const urls = props.imgs.length > 0 ? props.imgs : [processedSrc.value]
    uni.previewImage({
        urls,
        current: processedSrc.value
    })
}

// 监听 src 变化，重置状态
watch(
    () => props.src,
    (newSrc) => {
        if (newSrc) {
            loading.value = true
            hasError.value = false
            imageLoaded.value = false
        }
    },
    { immediate: true }
)
</script>

<style scoped lang="scss">
.custom-image {
    display: inline-block;
    position: relative;

    image {
        width: 100%;
        height: 100%;
        display: block;

        // 默认情况：如果不需要淡入效果，直接显示
        &.no-fade {
            opacity: 1;
        }

        // 需要淡入效果时：初始透明，加载完成后显示
        &:not(.no-fade) {
            opacity: 0;
            transition: opacity 0.3s ease-in-out;

            &.fade-in {
                opacity: 1;
            }
        }
    }

    .placeholder {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 1;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .progress-bar {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 4rpx;
        background-color: rgba(0, 0, 0, 0.1);
        z-index: 2;

        .progress-fill {
            height: 100%;
            background-color: #409eff;
            transition: width 0.3s ease;
        }
    }

    .retry-btn {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 20rpx;
        background-color: rgba(255, 255, 255, 0.9);
        border-radius: 8rpx;
        z-index: 3;

        text {
            margin-top: 8rpx;
            font-size: 24rpx;
            color: #409eff;
        }
    }
}
</style>
